#ifndef _WII_AUDIO_H_
#define _WII_AUDIO_H_

#include "base_audio.h"
#include "math/counter.h"

struct stb_vorbis;
namespace audio
{
class	WiiAudio : public Audio
{
public:
	static WiiAudio&	Instance();

	virtual AudioFile		LoadSoundFromMemory(vfs::LoadedBlock& Data, bool Repeat = false);
	virtual AudioHandle		PlaySFX(AudioFile	ID , float AudioBias);
	virtual AudioHandle		PlayMusic(const std::string& Name, float AudioBias = 1.0f, bool Repeat = true);
	virtual AudioHandle		PlayMusicH(AudioFile, float AudioBias = 1.0f) ;
	virtual void			Init(const std::string& AudioSet);
	virtual void			Shutdown(); 
	virtual bool			IsPlaying(AudioHandle Handle);
	virtual void			StopSound(AudioHandle Handle);
	virtual void			StopMusic();
	virtual void			PauseAll();
	virtual void			RestartAll() ;
	virtual void			SetMusicVolume(int	Volume);
	virtual unsigned int	GetFileSize(AudioHandle	Handle);

protected:
			WiiAudio() : 
				Audio()	{			} ;
	virtual					~WiiAudio(){};
	
	static void 			AudioFrameCallback(void);
	static void 			VoiceCallback(void * voiceIn);
	
	
	void*					m_pBuffer;
	void*					m_pMixBuffer;
	
	enum					DECODE_STATUS
	{
		DECODE_PROCESSING,
		DECODE_PROCESSING_COMPLETE,
		DECODE_STREAM_END,
		DECODE_ERROR
	};
	struct					OggStream
	{
		static const int	MUSIC_BUFFER = 1024 * 32 * 2;
		static const int	WORKER_BUFFER = MUSIC_BUFFER/2;	// needs to hold 1 buffer worth
		static const int	WORKER_STACK_SIZE = 1024 * 16;	// needs to be quite hefty due to the Vorbis decoder

		//  Raw buffer holds data from file. Decoded buffer holds uncompressed memory
		short				WorkerBufferA[WORKER_BUFFER] ATTRIBUTE_ALIGN(32);
		short				MusicBufferA[MUSIC_BUFFER] ATTRIBUTE_ALIGN(32);
		char				DecodeStackA[WORKER_STACK_SIZE] ATTRIBUTE_ALIGN(32);

		int					MusicBufferEnd;		// end position
		unsigned int		MusicBufferPos;		// position in stream
		unsigned int		MusicBufferHalf;	// midpoint in stream
		
		
		bool				Repeat;				// does it repeat
		
		unsigned char*		RawBufferA;
		int					RawBufferSize;	// how much of the RAW_BUFFER is used?

		int					FileBytesRead;
		
		// get some stream info as well?
		stb_vorbis *		pStream; 
		int					Channels;
		int					Samples;
		int					SampleRate;
		int					VoiceID;
		
		// worker thread to fill the buffer
		// since it'll take too long to decompress the OGG file otherwise
		OSThread			Worker;							
		DECODE_STATUS		DecodeStatus;
		static void*		WorkerThreadFn(void* pData);
		void				WaitForWorker();
	};
	void					ShutdownStream(OggStream* pStream);
	enum					STREAM_OPTIONS
	{
		STREAM_FIRST,
		STREAM_FIRST_HALF,
		STREAM_SECOND_HALF
	};
	bool					ProcessStream(STREAM_OPTIONS Option,OggStream* pStream, AXVPB* pVoice);

	struct					VoiceData
	{
		AXVPB*				pVoice;
		unsigned int		State;
		math::Counter		FadeOut;
		bool				ShouldFadeOut;
		OggStream*			pStream;
	};
	VoiceData				m_VoiceA[AX_MAX_VOICES];
	
	OggStream*				m_pMusic;	
	// do we provide ramp in-ramp out for new music?
};

} // namespace audio
#endif //_WII_AUDIO_H_